package com.tqjc.system.core.pipeline.thread;

import com.alibaba.fastjson.JSON;
import com.tqjc.system.common.constant.AddTaskConstant;
import com.tqjc.system.common.constant.GlobalConstant;
import com.tqjc.system.common.constant.RemoteURLConstant;
import com.tqjc.system.common.entity.BO.PLCWriteRequestParamBO;
import com.tqjc.system.common.entity.BO.ResponseLabelDataBO;
import com.tqjc.system.common.entity.BO.TankCarTaskInfoBO;
import com.tqjc.system.common.enums.SpanEnum;
import com.tqjc.system.common.enums.TankCarNoEnum;
import com.tqjc.system.core.pipeline.util.ScanUtils;
import com.tqjc.system.core.util.HttpsUtils;
import com.tqjc.system.core.util.PLCHttpsUtils;
import com.tqjc.system.core.util.SpringUtils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.Queue;

/**
 * @author 86195
 * @version 1.0
 * @description 发送槽车位置现场
 * @date 2023/10/17 16:57
 */
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
@Slf4j
public class SendTankPositionThread extends Thread{


    /**
     * 槽车号
     */
    private String tankCarNo;

    @Override
    public void run() {
        //获得槽车枚举信息

        TankCarNoEnum tankCarNoEnum = TankCarNoEnum.getEnum(tankCarNo);
        while (true) {
            try {
                //槽车任务信息
                Queue<TankCarTaskInfoBO> queue = AddTaskConstant.TANK_CAR_QUEUE_MAP.get(tankCarNo);
                TankCarTaskInfoBO tankCarTaskInfoBO = queue.poll();
                Map tankCarParamMap = new HashMap();
                tankCarParamMap.put(GlobalConstant.STRING_SN,GlobalConstant.TANK_CAR_SN_VAL);
                if(tankCarTaskInfoBO != null){
                    String taskType = tankCarTaskInfoBO.getTaskType();
                    String spanNo = tankCarTaskInfoBO.getSpanNo();
                    SpanEnum spanEnum = SpanEnum.getSpanEnum(spanNo);
                    log.info("{}#槽车有任务了,任务类型是{},要去{}",tankCarNo,taskType,spanEnum.getDesc());
                    if(AddTaskConstant.TANK_CAR_TASK_TYPE_ADD.equals(taskType)){
                        //执行加料动作
                        String targetValue = spanEnum.getTankCarIndex().get(tankCarNo);
                        //与PLC交互，执行移动
                        doWriteReq(taskType, tankCarNoEnum, targetValue);
                        log.info("{}#槽车有任务了,任务类型是{},要去{},已经完成",tankCarNo,taskType,spanEnum.getDesc());
                    } else {
                        //执行卸料任务  目标位置是固定的
                        String targetValue = AddTaskConstant.HEAT_SPAN_TANKCAR_INDEX;
                        //与PLC交互，执行移动
                        doWriteReq(taskType, tankCarNoEnum, targetValue);
                        log.info("{}#槽车有任务了,任务类型是{},已经完成",tankCarNo,taskType);
                    }
                    String tankCarName = tankCarNoEnum.getTankName();
                    tankCarParamMap.put(GlobalConstant.STRING_LABEL,tankCarName + GlobalConstant.FINISH_LABEL);
//                                currentVal = true;
                    //任务是否完成
                    long startTime = System.currentTimeMillis();
                    //延时等待再去读值
                    Thread.sleep(8*1000);
                    while (true){
                        log.info("异步线程判断槽车是否到位中。。。。");
                        ResponseLabelDataBO taskFlagDataBO = HttpsUtils.sendPost(RemoteURLConstant.URL_READBC, JSON.toJSONString(tankCarParamMap), ResponseLabelDataBO.class);
                        Map<String, String> taskFlagContent = taskFlagDataBO.getContent();
                        boolean currentVal = taskFlagContent != null ? Boolean.valueOf(taskFlagContent.get("currentVal").toLowerCase() ): false;
                        if(currentVal){
                            //槽车动作已完成
                            ScanUtils.setTankCarScanActFinish(TankCarNoEnum.getEnumByCarNo(tankCarNo),true);
                            //槽车任务执行复位
                            log.info("异步线程判断槽车已到位,复位点位数据。。。。");
                            resetVal(tankCarNoEnum);
                            break;
                        }
                        Thread.sleep(1*1000);
                        long endTime = System.currentTimeMillis();
                        if(endTime - startTime > 20 * 60 * 1000){
                            log.error("槽车长时间未返回完成信号");
                            resetVal(tankCarNoEnum);
                            break;
                        }
                    }

                } else {
                    Thread.sleep(1*1000);
                }
            } catch (Exception e){
                log.error("槽车移动出现异常",e);
                try {
                    //槽车任务执行复位
                    log.info("出现异常，异步线程判断槽车已到位,复位点位数据。。。。");
                    resetVal(tankCarNoEnum);
                } catch (Exception ee){
                }
            }
        }

    }

    private void resetVal(TankCarNoEnum tankCarNoEnum) throws Exception {
        Object[] taskExecuteInfo = tankCarNoEnum.getPLCInfoArray()[2];
        PLCWriteRequestParamBO paramBO = PLCWriteRequestParamBO.builder().dataType((Integer) taskExecuteInfo[1])
                .address((String) taskExecuteInfo[0]).macSN(tankCarNoEnum.getMacSN()).label((String) taskExecuteInfo[2]).build();
        paramBO.setValue(AddTaskConstant.TANK_CAR_NOT_ALLOW_MOVE);
        PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC, paramBO);
    }

    private void doWriteReq(String taskType, TankCarNoEnum tankCarNoEnum, String targetValue) throws Exception {
        Object[][] array = tankCarNoEnum.getPLCInfoArray();
        String macSN = tankCarNoEnum.getMacSN();
        for (int i = 0;i<array.length;i++){
            //二维数组 array 目标位置   任务类型  执行
            //写目标位置,再写任务类型，最后写执行
            Object[] info = array[i];
            //一维数组   Object[地址,数据类型,label]
            PLCWriteRequestParamBO paramBO = PLCWriteRequestParamBO.builder().macSN(macSN)
                    .address((String) info[0]).dataType((Integer) info[1]).label((String) info[2]).build();
            String value = getValue(targetValue, taskType,i);
            paramBO.setValue(value);
            try {

                PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC,paramBO);
            } catch (Exception e){
                log.error("写值操作异常",e);
                throw e;

            }

        }
    }

    private String getValue(String targetValue, String taskType, int j) {
        switch (j){
            //根据下标返回值的含义
            case 0:
                //目标位置
                return targetValue;
            case 1:
                //任务类型
                return taskType;
            case 2:
                return AddTaskConstant.TANK_CAR_ALLOW_MOVE;
        }
        return null;
    }
}
